import classNames from 'classnames';
import ResizeObserver from 'rc-resize-observer';
import React, { useCallback, useContext, useRef } from 'react';
import TabContext from '../TabContext';
import useIndicator from '../hooks/useIndicator';
import useUpdate, { useUpdateState } from '../hooks/useUpdate';
import { TabNavListProps, TabSizeMap } from '../interface';
import TabNode from './TabNode';

const TabNavList: React.FC<TabNavListProps> = (props) => {
  const { prefixCls, tabs } = useContext(TabContext);
  const tabListRef = useRef<HTMLDivElement>(null);
  const containerRef = useRef<HTMLDivElement>(null);
  const {
    id,
    style,
    tabBarListStyle,
    animated,
    activeKey,
    tabPosition,
    tabBarGutter,
    onTabClick,
  } = props;

  const tabPositionTopOrBottom =
    tabPosition === 'top' || tabPosition === 'bottom';

  const [tabSizes, setTabSizes] = useUpdateState<TabSizeMap>(new Map()); //{width,height,left:到父级左边的距离，top:到父级上边的距离}

  const tabNodes: React.ReactElement[] = tabs.map((tab, i) => {
    const { key } = tab;
    return (
      <TabNode
        id={id}
        prefixCls={prefixCls}
        key={key}
        tab={tab}
        /* first node should not have margin left */
        style={i === 0 ? undefined : { marginLeft: tabBarGutter }}
        active={key === activeKey}
        onClick={(e) => {
          onTabClick(key, e);
        }}
        onFocus={() => {
          // console.log('--TabNavList--onFocus--key--', key);
        }}
      />
    );
  });

  const getTabSize = useCallback(
    (tab: HTMLElement, containerRect: { x: number; y: number }) => {
      // tabListRef
      const { offsetWidth, offsetHeight, offsetTop, offsetLeft } = tab; //offsetTop, offsetLeft :距离父元素的相对距离, offsetWidth/offsetHeight:与 box-sizing,padding,border有关，是计算属性，精确到整数
      const { width, height, x, y } = tab.getBoundingClientRect(); //x/left,y/top: 距离视口的相对距离， width/height: css样式中写的width,height 与box-sizing、padding,border无关  （47.984375） 精确到6位小数
      // const tabBoundingClientRect = tab.getBoundingClientRect()
      // console.log('--TabNavList--offsetWidth, offsetHeight, offsetTop, offsetLeft--tabBoundingClientRect--:', offsetWidth, offsetHeight, offsetTop, offsetLeft, tabBoundingClientRect);

      // 没有box-sizing/padding/border干扰下，绝对值肯定小于1
      if (Math.abs(width - offsetWidth) < 1) {
        return [width, height, x - containerRect.x, y - containerRect.y];
      }

      return [offsetWidth, offsetHeight, offsetLeft, offsetTop];
    },
    [],
  );

  // 1.Update buttons records
  const updateTabSizes = () =>
    setTabSizes(() => {
      const newSizes: TabSizeMap = new Map();
      const listRect = tabListRef.current?.getBoundingClientRect();
      // console.log('--TabNavList--listRect--:', listRect);

      tabs.forEach(({ key }) => {
        const btnNode = tabListRef.current?.querySelector<HTMLElement>(
          `[data-node-key="${key}"]`,
        );
        if (btnNode) {
          const [width, height, left, top] = getTabSize(btnNode, listRect!);

          newSizes.set(key, {
            width,
            height,
            left,
            top,
          });
        }
      });
      return newSizes;
    });

  // useEffect(() => {
  //   updateTabSizes();
  // }, [tabs.map(tab => tab.key).join('_')]);

  //ym-tabs-nav-list渲染完之后 保证callback函数每次被触发一下，只执行一次
  const onListHolderResize = useUpdate(() => {
    updateTabSizes();
  });

  // =================== 2.Link & Operations ===================
  // 注： onTabClick- props.key改变 这里useMemo会导致activeTabOffset不会改变，useIndicator不执行，ink-bar样式没有变化
  // const activeTabOffset = useMemo(() => tabSizes.get(activeKey), [tabSizes, tabs.map(tab => tab.key).join('_')]);
  const activeTabOffset = tabSizes.get(activeKey);
  const { style: indicatorStyle } = useIndicator({
    activeTabOffset,
    horizontal: tabPositionTopOrBottom,
  });

  return (
    <div
      ref={containerRef}
      role="tablist"
      className={classNames(`${prefixCls}-nav`)}
      style={style}
    >
      <div className={classNames(`${prefixCls}-nav-wrap`)}>
        <ResizeObserver onResize={onListHolderResize}>
          <div
            ref={tabListRef}
            className={`${prefixCls}-nav-list`}
            style={tabBarListStyle}
          >
            {tabNodes}
            <div
              className={classNames(`${prefixCls}-ink-bar`, {
                [`${prefixCls}-ink-bar-animated`]: animated.inkBar,
              })}
              style={indicatorStyle}
            />
          </div>
        </ResizeObserver>
      </div>
    </div>
  );
};

export default TabNavList;
